package com.blue.gateway.paycore.wxpay.pay;

import com.alibaba.fastjson.JSON;
import com.blue.gateway.common.Request;
import com.blue.gateway.common.request.PayQueryRequest;
import com.blue.gateway.config.BaseChannelConfig;
import com.blue.gateway.dto.Result;
import com.blue.gateway.dto.ResultWrapper;
import com.blue.gateway.enums.PayChannelEnum;
import com.blue.gateway.enums.ResultCodeEnum;
import com.blue.gateway.utils.RandomUtil;
import com.blue.gateway.utils.http.HttpClientsUtil;
import com.blue.gateway.utils.sign.WxPaySignature;
import com.blue.gateway.annotation.Channel;
import com.blue.gateway.common.response.PayQueryResponse;
import com.blue.gateway.config.WxConfig;
import com.blue.gateway.paycore.wxpay.WxPayConstants;
import com.blue.gateway.enums.ServiceChannelEnum;
import com.blue.gateway.utils.XmlUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 * @author xiaoyiming
 * @date 2020/5/4 22:18
 * @depiction 查询订单
 * https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_2
 */
@Slf4j
@Channel(PayChannel = PayChannelEnum.WX, ServiceChannel = ServiceChannelEnum.PAY_QUERY)
public class WxPayQueryService extends WxPayService {
    @Override
    public Result validate(Request request) {
        PayQueryRequest payRequest = (PayQueryRequest) request;
        if (StringUtils.isBlank(payRequest.getTradeNo())
                && StringUtils.isBlank(payRequest.getOutTradeNo())) {
            return ResultWrapper.fail(ResultCodeEnum.CONFIG_ILLEGAL);
        }
        return ResultWrapper.success();
    }

    @Override
    public BaseChannelConfig getConfig(Request request) {
        return super.getConfig(request);
    }

    @Override
    public String generateParams(Request request, BaseChannelConfig channelConfig) {
        PayQueryRequest payRequest = (PayQueryRequest) request;
        WxConfig wxConfig = (WxConfig) channelConfig;

        SortedMap<String, String> params = new TreeMap<>();
        params.put("appid", wxConfig.getAppId());
        params.put("mch_id", wxConfig.getMchId());
        params.put("nonce_str", RandomUtil.getRandomStr());
        if (StringUtils.isNotEmpty(payRequest.getTradeNo())) {
            params.put("transaction_id", payRequest.getTradeNo());
        }
        if (StringUtils.isNotEmpty(payRequest.getOutTradeNo())) {
            params.put("out_trade_no", payRequest.getOutTradeNo());
        }
        String sign = WxPaySignature.sign(params, wxConfig.getParterKey());
        params.put("sign", sign);

        return XmlUtil.mapToXML(params);
    }

    @Override
    public String execute(String requestParams, BaseChannelConfig channelConfig) {
        // 发送请求
        String executeResult = null;
        try {
            executeResult = HttpClientsUtil.httpClientPost(WxPayConstants.WX_PAY_QUERY_GATEWAY, requestParams);
        } catch (Exception e) {
            // do nothing
        }
        return executeResult;
    }

    /**
     * https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_2
     * <xml>
     * <return_code><![CDATA[SUCCESS]]></return_code>
     * <return_msg><![CDATA[OK]]></return_msg>
     * <appid><![CDATA[wxd898fcb01713c658]]></appid>
     * <mch_id><![CDATA[1483469312]]></mch_id>
     * <nonce_str><![CDATA[ZnEXD0hs0tpKWaNp]]></nonce_str>
     * <sign><![CDATA[DC8CFA8B671E7F5E81FE2226E1727EE7]]></sign>
     * <result_code><![CDATA[SUCCESS]]></result_code>
     * <openid><![CDATA[oTgZpwcqJrSlwSeYPoXaOrohFgXk]]></openid>
     * <is_subscribe><![CDATA[Y]]></is_subscribe>
     * <trade_type><![CDATA[NATIVE]]></trade_type>
     * <bank_type><![CDATA[OTHERS]]></bank_type>
     * <total_fee>1</total_fee>
     * <fee_type><![CDATA[CNY]]></fee_type>
     * <transaction_id><![CDATA[4200000560202005043756846395]]></transaction_id>
     * <out_trade_no><![CDATA[27898754987988971]]></out_trade_no>
     * <attach><![CDATA[]]></attach>
     * <time_end><![CDATA[20200504220628]]></time_end>
     * <trade_state><![CDATA[SUCCESS]]></trade_state>
     * <cash_fee>1</cash_fee>
     * <trade_state_desc><![CDATA[支付成功]]></trade_state_desc>
     * <cash_fee_type><![CDATA[CNY]]></cash_fee_type>
     * </xml>
     * <p></p>
     * SUCCESS—支付成功
     * REFUND—转入退款
     * NOTPAY—未支付
     * CLOSED—已关闭
     * REVOKED—已撤销（付款码支付）
     * USERPAYING--用户支付中（付款码支付）
     * PAYERROR--支付失败(其他原因，如银行返回失败)
     *
     * @param executeResult
     * @return
     */
    @Override
    public Result analysisResult(String executeResult) {
        PayQueryResponse payResponse = new PayQueryResponse();
        Map<String, String> result = XmlUtil.toMap(executeResult);
        payResponse.setMsg(result.get("return_msg"));
        payResponse.setData(JSON.toJSONString(result));
        if (WxPayConstants.SUCCESS.equals(result.get("return_code"))) {
            payResponse.setTradeState(result.get("trade_state"));
            payResponse.setTradeStateDesc(result.get("trade_state_desc"));
            payResponse.setOpenId(result.get("openid"));
            return ResultWrapper.success(payResponse);
        }

        return ResultWrapper.fail(payResponse);
    }

}
